package xcmg.device.service.threeGuaranteesPur;

import com.github.pagehelper.PageInfo;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import xcmg.device.dao.entity.threeGuaranteesPur.ThreeGuaranteesOutDO;
import xcmg.device.dao.entity.threeGuaranteesPur.ThreeGuaranteesPurDO;
import xcmg.device.dao.entity.threeGuaranteesPur.ThreeReverseDO;
import xcmg.device.dao.entity.threeGuaranteesPur.ThreeReverseDetailDO;
import xcmg.device.dao.mapper.threeGuaranteesPur.ThreeGuaranteesOutMapper;
import xcmg.device.dao.mapper.threeGuaranteesPur.ThreeGuaranteesPurMapper;
import xcmg.device.dao.mapper.threeGuaranteesPur.ThreeReverseDetailMapper;
import xcmg.device.dao.mapper.threeGuaranteesPur.ThreeReverseMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseDeliveryMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseInventoryMapper;
import xcmg.device.infra.DateUtil;
import xcmg.device.infra.ErrorCode;
import xcmg.device.infra.ExportUtil;
import xcmg.device.infra.enums.BillDesc;
import xcmg.device.service.GenDocumentService;
import xcmg.device.service.company.CompanyInfoService;
import xcmg.device.service.vo.threeGuaranteesPur.ThreeReverseAddVO;
import xcmg.device.service.vo.threeGuaranteesPur.ThreeReverseDetailVO;
import xcmg.device.service.vo.threeGuaranteesPur.ThreeReverseVO;
import xcmg.device.service.warehouse.CommonService;
import xcmg.device.service.warehouse.WarehouseInboundService;
import yb.ecp.fast.feign.FastGenClient;
import yb.ecp.fast.infra.infra.ActionResult;
import yb.ecp.fast.infra.infra.PageCommonVO;
import yb.ecp.fast.infra.infra.SearchCommonVO;
import yb.ecp.fast.infra.util.ListUtil;
import yb.ecp.fast.infra.util.PageHelperPlus;
import yb.ecp.fast.infra.util.StringUtil;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class ThreeReverseService {

    @Autowired
    private GenDocumentService genDocumentService;

    @Autowired
    private FastGenClient fastGenClient;

    @Autowired
    private HttpServletResponse response;

    @Autowired
    private CommonService commonService;

    @Autowired
    private ThreeReverseMapper threeReverseMapper;

    @Autowired
    private ThreeReverseDetailMapper threeReverseDetailMapper;

    @Autowired
    private ThreeReverseDetailService threeReverseDetailService;

    @Autowired
    private ThreeGuaranteesOutMapper threeGuaranteesOutMapper;

    @Autowired
    private ThreeGuaranteesPurMapper threeGuaranteesPurMapper;

    @Autowired
    private ThreeGuaranteesOutService threeGuaranteesOutService;

    @Autowired
    private WarehouseInboundService warehouseInboundService;

    @Autowired
    private ThreeGuaranteesPurService threeGuaranteesPurService;

    @Autowired
    private WarehouseDeliveryMapper warehouseDeliveryMapper;

    @Autowired
    private CompanyInfoService companyInfoService;

    @Autowired
    WarehouseInventoryMapper warehouseInventoryMapper;

    /**
     * @Author: WangKe
     * @Description: 新增三包出库撤销单
     * @Date: 2018/7/11 0011
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode add(ThreeReverseAddVO threeReverseAddVO, String userId, String orgId)throws Exception{
        ActionResult<String> textResult = fastGenClient.textGuid();
        if (textResult.getCode() != ErrorCode.Success.getCode())
        {
            return ErrorCode.IllegalArument;
        }
        ThreeReverseVO threeReverseVO = threeReverseAddVO.getHeaderInfo();

        ThreeGuaranteesOutDO threeGuaranteesOutDO = threeGuaranteesOutMapper.itemByNo(threeReverseVO.getBusinessOrder(), orgId);
        if(threeGuaranteesOutDO == null){
            throw new Exception("未找到三包出库单");
        }
        ThreeGuaranteesPurDO threeGuaranteesPurDO = threeGuaranteesPurMapper.itemByNo(threeGuaranteesOutDO.getPurchaseNo(), orgId);
        if(threeGuaranteesPurDO == null){
            throw new Exception("未找到三包申请单");
        }

        ThreeReverseDO threeReverseDO = new ThreeReverseDO();
        BeanUtils.copyProperties(threeReverseVO, threeReverseDO);
        threeReverseDO.setId(textResult.getValue());
        threeReverseDO.setReverseOrder(genDocumentService.getDocumentNo(BillDesc.ThreeReverse));
        threeReverseDO.setAgentId(threeGuaranteesPurDO.getCustomerId());
        threeReverseDO.setAgentName(threeGuaranteesPurDO.getCustomerName());
        threeReverseDO.setWarehouseCode(threeGuaranteesOutDO.getOutLocation());
        threeReverseDO.setInArea(threeGuaranteesOutDO.getOutArea());
        threeReverseDO.setSapInArea(threeGuaranteesOutDO.getSapOutArea());
        threeReverseDO.setIsPosting(StringUtil.isNullOrEmpty(threeGuaranteesOutDO.getVoucherNo())?0:1);
        threeReverseDO.setState(0);
        threeReverseDO.setAuditState(0);
        threeReverseDO.setIsSapReverse(0);
        threeReverseDO.setCreateDate(new Date());
        threeReverseDO.setCreateId(userId);
        threeReverseDO.setOrgId(orgId);
        threeReverseDO.setCreateName(commonService.getUserName(userId));
        boolean success = threeReverseMapper.insert(threeReverseDO)>0;
        if(success){
            //新增冲销入库详情记录
            List<ThreeReverseDetailVO> detailVOList = threeReverseAddVO.getDetailList();
            if(CollectionUtils.isNotEmpty(detailVOList)){
                for(ThreeReverseDetailVO detail : detailVOList){
                    detail.setReverseOrder(threeReverseDO.getReverseOrder());
                    detail.setBusinessOrder(threeReverseDO.getBusinessOrder());
                    detail.setRealQty(detail.getAmount());
                    detail.setCreateId(userId);
                    detail.setCreateName(threeReverseDO.getCreateName());
                    detail.setOrgId(orgId);
                    success = threeReverseDetailService.add(detail).getCode()==0;
                    if(!success){
                        throw new Exception("新增三包冲销入库详情记录失败");
                    }
                }
            }

            //更新发货通知单和出库事务单的冲销状态
            threeGuaranteesOutService.updateReverseState(threeGuaranteesOutDO, 1, orgId);
        }
        return success? ErrorCode.Success: ErrorCode.Failure;
    }

    /**
     * @Author: WangKe
     * @Description: 审核三包冲销单
     * @Date: 2018/7/11 0011
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode audit(ThreeReverseVO threeReverseVO, String orgId, String userId)throws Exception{
        if(threeReverseVO == null || threeReverseVO.getAuditState() == 0){
            return ErrorCode.IllegalArument;
        }
        ThreeReverseDO threeReverseDO = threeReverseMapper.selectByPrimaryKey(threeReverseVO.getId());
        if(threeReverseDO == null){
            return ErrorCode.IllegalArument;
        }

        //查找三包出库单
        ThreeGuaranteesOutDO threeGuaranteesOutDO = threeGuaranteesOutMapper.itemByNo(threeReverseDO.getBusinessOrder(), orgId);
        if(threeGuaranteesOutDO == null){
            throw new Exception("未找到三包出库单");
        }

        boolean success;
        if(threeReverseVO.getAuditState() == 1){ //审核通过时，执行冲销动作
            if(StringUtil.isNullOrEmpty(threeGuaranteesOutDO.getVoucherNo())){
                throw new Exception("三包出库单未过账");
            }
            List<ThreeReverseDetailDO> reverseDetailDOList = threeReverseDetailMapper.selectByMainNo(threeReverseDO.getReverseOrder(), orgId);
            if(ListUtil.isNullOrEmpty(reverseDetailDOList)){
                throw new Exception("未找到三包冲销入库单详情记录");
            }
            //查找所有部分出库或者全部出库的详情记录
            List<ThreeReverseDetailDO> dataList = new ArrayList<>();
            for(ThreeReverseDetailDO reverseDetailDO : reverseDetailDOList){
                if(reverseDetailDO.getAmount().compareTo(BigDecimal.ZERO) > 0){
                    dataList.add(reverseDetailDO);
                }
            }
            if(ListUtil.isNullOrEmpty(dataList)){ //零件未出库时，状态直接标记为已完成
                threeReverseDO.setState(2);

                success = threeReverseDetailMapper.updateStateByOrder(threeReverseDO.getReverseOrder(), 2, orgId)>0;
                if(!success){
                    throw new Exception("更新三包冲销单详情记录失败");
                }
            }

            //更新三包出库单和出库事务单的冲销状态
            success = threeGuaranteesOutService.updateReverseState(threeGuaranteesOutDO, 2, orgId);
            if(!success){
                throw new Exception("更新三包出库单和出库事务单的冲销状态失败");
            }

            //如果零件部分或者全部出库，生成入库事务单
            if(threeReverseDO.getState() != 2){
                success = warehouseInboundService.saveByThreeReverseIn(threeReverseDO, reverseDetailDOList, userId, orgId);
                if(!success){
                    throw new Exception("生成入库事务单失败");
                }
            }

            //三包申请单状态修改
            success = threeGuaranteesPurService.updateByThreeReverse(threeGuaranteesOutDO, orgId);
            if(!success){
                throw new Exception("更新三包申请单发货数量和状态失败");
            }
        }else{
            //更新三包出库单和出库事务单的冲销状态
            threeGuaranteesOutService.updateReverseState(threeGuaranteesOutDO, 3, orgId);
        }
        threeReverseDO.setAuditState(threeReverseVO.getAuditState());
        threeReverseDO.setAuditNote(threeReverseVO.getAuditNote());
        threeReverseDO.setAuditUserId(userId);
        threeReverseDO.setAuditUserName(commonService.getUserName(userId));
        threeReverseDO.setAuditDate(new Date());
        success = threeReverseMapper.update(threeReverseDO)>0;
        return success?ErrorCode.Success:ErrorCode.Failure;
    }

    /**
     * @Author: WangKe
     * @Description: 删除冲销入库单据
     * @Date: 2018/7/11 0011
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode delete(List<String> ids, String orgId)throws Exception{
        int num = threeReverseMapper.findNumForNotAudit(ids);
        if(num > 0){
            throw new Exception("只能删除未审核状态的冲销入库单");
        }
        List<String> orderList = threeReverseMapper.findOrderList(ids);
        List<String> deliveryOrderList = threeReverseMapper.findDeliveryOrderList(ids);
        boolean success = threeReverseMapper.remove(ids)>0;
        //删除入库详情记录
        if(success && CollectionUtils.isNotEmpty(orderList)){
            success = threeReverseDetailMapper.removeByInOrderList(orderList, orgId)>0;
            if(!success){
                throw new Exception("删除冲销入库详情记录失败");
            }

            //更新三包出库单冲销状态
            success = threeGuaranteesOutMapper.updateReverseState(deliveryOrderList, 0, orgId)>0;
            if(!success){
                throw new Exception("更新三包出库单冲销状态失败");
            }

            //更新出库事务单冲销状态
            success = warehouseDeliveryMapper.updateReverseState(deliveryOrderList, 0, orgId)>0;
            if(!success){
                throw new Exception("更新出库事务单冲销状态失败");
            }
        }
        return success? ErrorCode.Success: ErrorCode.WarehouseIdError;
    }

    /**
     * @Author: WangKe
     * @Description: 查找冲销入库单据列表
     * @Date: 2018/7/11 0011
     */
    public PageCommonVO list(SearchCommonVO<ThreeReverseVO> condition) {
        PageCommonVO<ThreeReverseVO> pageCommonVO = new PageCommonVO();
        PageHelperPlus.orderBy("create_date desc");
        PageHelperPlus.startPage(condition.getPageNum(), condition.getPageSize());
        List<ThreeReverseDO> doList = threeReverseMapper.list(condition.getFilters());
        List<ThreeReverseVO> voList = new ArrayList<>();
        for (ThreeReverseDO entity : doList) {
            ThreeReverseVO model = new ThreeReverseVO();
            BeanUtils.copyProperties(entity, model);
            voList.add(model);
        }
        pageCommonVO.setPageInfo(new PageInfo(doList));
        pageCommonVO.setPageInfoList(voList);
        return pageCommonVO;
    }

    /**
     * @Author: WangKe
     * @Description: 根据主键或者业务单号查找记录
     * @Date: 2018/7/11 0011
     */
    public ThreeReverseAddVO findByPK(String id){
        ThreeReverseAddVO model = new ThreeReverseAddVO();
        ThreeReverseDO entity = threeReverseMapper.selectByPrimaryKey(id);
        if(entity == null){
            return null;
        }

        List<ThreeReverseDetailDO> doList = threeReverseDetailMapper.selectByMainNo(entity.getReverseOrder(), entity.getOrgId());
        List<ThreeReverseDetailVO> voList = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(doList)){
            ThreeReverseDetailVO threeReverseDetailVO;
            for(ThreeReverseDetailDO m:doList){
                threeReverseDetailVO = new ThreeReverseDetailVO();
                BeanUtils.copyProperties(m, threeReverseDetailVO);
                threeReverseDetailVO.setEnableNum(warehouseInventoryMapper.findEnableNum(m.getMaterialNo(),entity.getOrgId(),entity.getWarehouseCode()));
                voList.add(threeReverseDetailVO);
            }
        }
        ThreeReverseVO threeReverseVO = new ThreeReverseVO();
        BeanUtils.copyProperties(entity, threeReverseVO);

        model.setHeaderInfo(threeReverseVO);
        model.setDetailList(voList);
        return model;
    }

    public ThreeReverseAddVO findByPK(String id,String type){
        ThreeReverseAddVO model = new ThreeReverseAddVO();
        ThreeReverseDO entity = threeReverseMapper.selectByPrimaryKey(id);
        if(entity == null){
            return null;
        }

        List<ThreeReverseDetailDO> doList = threeReverseDetailMapper.selectByMainNo(entity.getReverseOrder(), entity.getOrgId());
        List<ThreeReverseDetailVO> voList = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(doList)){
            ThreeReverseDetailVO threeReverseDetailVO;
            for(ThreeReverseDetailDO m:doList){
                threeReverseDetailVO = new ThreeReverseDetailVO();
                BeanUtils.copyProperties(m, threeReverseDetailVO);
                threeReverseDetailVO.setEnableNum(warehouseInventoryMapper.findEnableNum(m.getMaterialNo(),entity.getOrgId(),entity.getWarehouseCode()));
                voList.add(threeReverseDetailVO);
            }
        }
        ThreeReverseVO threeReverseVO = new ThreeReverseVO();
        BeanUtils.copyProperties(entity, threeReverseVO);

        model.setHeaderInfo(threeReverseVO);
        model.setDetailList(voList);
        return model;
    }

    public void export(List<String> ids)throws Exception{
        invokeExport(threeReverseMapper.findByIds(ids));
    }

    /**
     * @Author: WangKe
     * @Description: 导出冲销入库记录列表
     * @Date: 2018/7/11 0011
     */
    public void exportAll(ThreeReverseVO condition)throws Exception{
        Integer count = threeReverseMapper.findCountForExportAll(condition);
        List<ThreeReverseDO> dataList = new ArrayList<>();
        int times = count/500+1;
        for(int i=0; i<times; i++){
            PageHelperPlus.startPage(i + 1, 500, "create_date desc");
            dataList.addAll(threeReverseMapper.list(condition));
        }
        invokeExport(dataList);
    }

    /**
     * @Author: WangKe
     * @Description: 导出冲销入库记录列表
     * @Date: 2018/7/11 0011
     */
    private void invokeExport(List<ThreeReverseDO> doList)throws Exception{
        String title = "冲销入库数据导出";
        String[] rowsName = new String[]{"序号","冲销入库单号","三包出库单号","客户名称","仓库编码",
                "入库状态", "审核状态", "三包出库单是否过账", "SAP是否冲销成功", "创建人", "制单时间", "备注"};
        List<Object[]>  dataList = new ArrayList<>();
        Object[] objs;
        for (int i = 0; i < doList.size(); i++) {
            ThreeReverseDO exportDO = doList.get(i);
            objs = new Object[rowsName.length];
            objs[0] = i+1;
            objs[1] = exportDO.getReverseOrder();
            objs[2] = exportDO.getBusinessOrder();
            objs[3] = exportDO.getAgentName();
            objs[4] = exportDO.getWarehouseCode();
            objs[5] = getState(exportDO.getState());
            objs[6] = getAuditState(exportDO.getAuditState());
            objs[7] = (exportDO.getIsPosting()==null || exportDO.getIsPosting()==0)?"否":"是";
            objs[8] = (exportDO.getIsSapReverse()==null || exportDO.getIsSapReverse()==0)?"否":"是";
            objs[9] = exportDO.getCreateName();
            objs[10] = DateUtil.formatDateTime(exportDO.getCreateDate());
            objs[11] = exportDO.getNote();
            dataList.add(objs);
        }
        ExportUtil exportUtil = new ExportUtil(title, rowsName, dataList);
        exportUtil.export(response);
    }

    private String getState(Integer state){
        if(state == null){
            state = 0;
        }
        if(state == 0 ){
            return "未入库";
        }else if(state == 1 ){
            return "部分入库";
        }else if(state == 2 ){
            return "已入库";
        }else{
            return "强制结单";
        }
    }

    private String getAuditState(Integer state){
        if(state == null){
            state = 0;
        }
        if (state == 0) {
            return "待审核";
        } else if (state == 1) {
            return "审核通过";
        } else {
            return "审核拒绝";
        }
    }

//    @Transactional(rollbackFor = Exception.class)
//    public ErrorCode sapPost(String id, String orgId) throws Exception {
//        ThreeReverseDO threeReverseDO = threeReverseMapper.selectByPrimaryKey(id);
//        if (threeReverseDO == null) {
//            return ErrorCode.IllegalArument;
//        }
//        if (threeReverseDO.getIsPosting() == 0) {
//            throw new Exception("该冲销单对应的三包出库单未过账");
//        }
//        if (threeReverseDO.getIsSapReverse() == 1) {
//            throw new Exception("该冲销单已经过账成功");
//        }
//
//        ImportParam importParam = fillImportParam(threeReverseDO, orgId);
//        LogHelper.monitor("========调用三包冲销过账接口开始========");
//        OutputParam outputParam = SAPCommonUtil.getData(importParam);
//        LogHelper.monitor("========调用三包冲销过账接口结束========");
//        if (null == outputParam || outputParam.getCode() != 0) {
//            LogHelper.error("sap返回值为null", ErrorCode.RequestIdError.getCode());
//            throw new Exception("sap返回值为null");
//        }
//        if ("OK".equals(outputParam.getDataHeader().get("RETURNCODE").toUpperCase())) {
//            ThreeReverseDO reverseDO = new ThreeReverseDO();
//            reverseDO.setId(id);
//            reverseDO.setIsSapReverse(1);
//            reverseDO.setVoucherNo(outputParam.getDataHeader().get("MBLNR_CX"));
//            reverseDO.setVoucherTime(outputParam.getDataHeader().get("MJAHR_CX"));
//            if (threeReverseMapper.update(reverseDO) > 0) {
//                return threeGuaranteesOutMapper.updateReverseSuccessState(threeReverseDO.getBusinessOrder(), 1, orgId)>0?ErrorCode.Success:ErrorCode.Failure;
//            }
//            return ErrorCode.Failure;
//        } else {
//            ThreeReverseDO reverseDO = new ThreeReverseDO();
//            reverseDO.setId(id);
//            reverseDO.setSapErrorMsg(outputParam.getDataHeader().get("RETURNMSG"));
//            threeReverseMapper.update(reverseDO);
//            //返回处理的消息
//            throw new Exception(outputParam.getDataHeader().get("RETURNMSG"));
//        }
//    }
//
//    private ImportParam fillImportParam(ThreeReverseDO threeReverseDO, String orgId) throws Exception {
//        CompanyInfoVO companyInfoVO = companyInfoService.info(threeReverseDO.getOrgId());
//        if (companyInfoVO == null || companyInfoVO.getSapCode() == null) {
//            LogHelper.error("同步sap过账时企业不存在,orgId:" + threeReverseDO.getOrgId(), ErrorCode.RequestIdError.getCode());
//            throw new Exception("同步sap过账时企业不存在");
//        }
//        ThreeGuaranteesOutDO outDO = threeGuaranteesOutMapper.itemByNo(threeReverseDO.getBusinessOrder(), orgId);
//        if(outDO == null || StringUtil.isNullOrEmpty(outDO.getVoucherNo())){
//            throw new Exception("三包出库单不存在或者物理凭证号为空");
//        }
//        ImportParam importParam = new ImportParam();
//        importParam.setFunction("ZPMS_MBST");
//        SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
//        Map<String, String> map = new HashMap<>();
//        map.put("MBLNR", outDO.getVoucherNo());
//        map.put("BUDAT", format.format(new Date()));
//        importParam.setCommonParamMap(map);
//        importParam.setSapCode(companyInfoVO.getSapCode());
//        return importParam;
//    }

    public int updateById(ThreeReverseDO threeReverseDO) {
        return threeReverseMapper.update(threeReverseDO);
    }

    public List<ThreeReverseDO> findBatchByIds(List<String> ids) {
        return threeReverseMapper.findBatchByIds(ids);
    }

    public boolean batchUpdateById(List<ThreeReverseDO> threeReverseDOList) {
        return threeReverseMapper.batchUpdateById(threeReverseDOList);
    }
}
